package com.atguigu.srb.core.service.impl;

import com.atguigu.srb.base.asserts.Asserts;
import com.atguigu.srb.base.response.ResponseEnum;
import com.atguigu.srb.base.util.JwtUtils;
import com.atguigu.srb.core.hfb.FormHelper;
import com.atguigu.srb.core.hfb.HfbConst;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.pojo.entity.UserAccount;
import com.atguigu.srb.core.pojo.entity.UserBind;
import com.atguigu.srb.core.mapper.UserBindMapper;
import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.service.UserAccountService;
import com.atguigu.srb.core.service.UserBindService;
import com.atguigu.srb.core.service.UserInfoService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.org.apache.bcel.internal.generic.RETURN;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 用户绑定表 服务实现类
 * </p>
 *
 * @author Atguigu
 * @since 2023-05-26
 */
@Service
public class UserBindServiceImpl extends ServiceImpl<UserBindMapper, UserBind> implements UserBindService {
    @Resource
    UserInfoService userInfoService;
    @Resource
    UserAccountService userAccountService;
    @Override
    public String bindHfb(UserBind userBind, String token) {
        //1、将绑定表单的数据和userId一起保存到user_bind表
        //1.1 判断会员之前是否已经绑定过：如果已经绑定过 拒绝请求
        //  根据身份证id和用户id 查询绑定hfb成功的账号 如果已存在 拒绝本次绑定请求
        Long userId = JwtUtils.getUserId(token);
        UserBind dbUserBind = this.getOne(Wrappers.lambdaQuery(UserBind.class)
                .eq(UserBind::getUserId, userId)
                .or() //如果userId存在 或者 idcard存在
                .eq(UserBind::getIdCard, userBind.getIdCard()));//每个会员的身份证号码只能绑定一个账户
        Asserts.assertNotTrue(dbUserBind!=null && dbUserBind.getStatus()!= null && dbUserBind.getStatus()==1 ,
                ResponseEnum.USER_BIND_IDCARD_EXIST_ERROR);

        //1.2 如果未绑定，本次保存绑定的数据
        //设置绑定数据必须的参数值：一个hfb的绑定数据 必须和一个会员的id对应
        if(dbUserBind==null){
            userBind.setUserId(userId);
            //如果会员已经提交过绑定请求但是未绑定成功 本次更新，否则新增
            this.save(userBind);
        }else{
            //更新数据：
            dbUserBind.setName(userBind.getName());
            dbUserBind.setIdCard(userBind.getIdCard());
            dbUserBind.setBankType(userBind.getBankType());
            dbUserBind.setBankNo(userBind.getBankNo());
            dbUserBind.setMobile(userBind.getMobile());
            this.updateById(dbUserBind);
        }

        //2、解析提交的绑定表单的数据 和hfb的开户表单页的地址拼接
        //响应让浏览器跳转到第三方的方式：
        //方式1- 后端返回一个重定向视图 让浏览器重定向访问第三方的接口地址
        //方式2- 后端也可以构建一个自动提交的表单字符传，前端展示到页面时 执行页面中的js 就可以触发表单自动提交

        Map<String, Object> params = new HashMap<>();
        //srb如果使用hfb，必须先到hfb中注册应用，hfb给srb分配了一个唯一的appId
        params.put("agentId", HfbConst.AGENT_ID);
        //要在hfb中开通hfb账户的会员 在srb中的唯一标识(userId)
        params.put("agentUserId",userId);
        //会员身份证号
        params.put("idCard",userBind.getIdCard());
        //会员真实姓名
        params.put("personalName",userBind.getName());
        params.put("bankType",userBind.getBankType());
        params.put("bankNo",userBind.getBankNo());
        params.put("mobile",userBind.getMobile());
        //会员开通hfb账户后，同步跳转回srb的地址(开通hfb成功的页面)
        //开户成功的页面地址：http://localhost:3000/user
        params.put("returnUrl","http://localhost:3000/user");
        //会员开通hfb账户后，hfb异步通知srb服务端 会员开通hfb账户的结果(可以更新user_info user_bind user_account)
        params.put("notifyUrl","http://192.168.1.170/api/core/userBind/notifyUrl");
        params.put("timestamp",System.currentTimeMillis());
        //签名：防止数据被篡改
        params.put("sign", RequestHelper.getSign(params));

        //参数1：hfb接收开户请求的地址(拼接后的表单自动提交的地址)  参数2：访问hfb开户接口需要的参数的map(会拼接到表单中作为表单项)
        return FormHelper.buildForm("http://localhost:9999/userBind/BindAgreeUserV2",params);

    }

    @Override
    public String bindNotifyUrl(HttpServletRequest request) {
        //1、获取参数：
        Map<String, Object> params = RequestHelper.switchMap(request.getParameterMap());
        //1.1 验证签名是否正确：防止被篡改数据  sign
        // params中包含了 hfb生成的签名
        // 我们可以使用params集合中除了sign以外的其他参数 再次生成一个sign
        // 如果hfb传入的签名sign和我们本地基于参数列表生成的签名sign一样 我们认为数据安全没有被篡改
        boolean signEquals = RequestHelper.isSignEquals(params);
        if(!signEquals){
//        Asserts.assertNotTrue(!signEquals , );
//        return "fail";
            System.out.println("参数签名校验失败");
            return "fail";
        }
        //1.2 校验验证码：resultCode为0001时才代表成功
        if(!"0001".equals(params.get("resultCode"))){
            System.out.println("resultCode验证失败：hfb处理绑定业务失败");
            return "fail";
        }
        //2、如果校验通过
        //hfb会员的编号
        String bindCode = params.get("bindCode").toString();
        //srb会员userInfo表中的id
        String agentUserId = params.get("agentUserId").toString();
        // 获取bindCode(在hfb开通的账户的唯一标识) 和agentUserId(srb中去hfb开户的会员的id)
        // 更新到userinfo  userbind  表中
        UserBind userBind = this.getOne(Wrappers.lambdaQuery(UserBind.class)
                .eq(UserBind::getUserId, agentUserId));

        userBind.setBindCode(bindCode);
        //1表示绑定成功
        userBind.setStatus(1);
        this.updateById(userBind);

        UserInfo userInfo = userInfoService.getById(agentUserId);
        //会员绑定hfb成功，也可以将会员绑定时使用的数据更新到userInfo表中
        userInfo.setName(userBind.getName());
        userInfo.setIdCard(userBind.getIdCard());
        userInfo.setBindCode(bindCode);
        userInfo.setBindStatus(1);
        userInfoService.updateById(userInfo);
        //3、新开户成功为会员初始化一个账户(初始账户余额为0)
        UserAccount userAccount = new UserAccount();
        userAccount.setAmount(new BigDecimal(0));
        userAccount.setUserId(userInfo.getId());
        userAccount.setFreezeAmount(new BigDecimal(0));
        userAccountService.save(userAccount);


        //返回操作成功
        return "success";
    }
}
